﻿using Confluent.Kafka;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using Octokit;
using SharpCompress.Common;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using WorkFlowCore.Common.Utils;
using static System.Net.WebRequestMethods;

namespace WorkFlowCore.Resources.GitResources
{
    public class GithubResourceManager : IResourceManager
    {

        private string owner;
        private string repoName;
        private string branchName; // 或者你要提交到的其他分支
        private string token;
        private string fileSubfix = ".png";//防止被过滤，统一给文件加了个后缀


        public GithubResourceManager(IOptions<GitResourceOptions> options)
        {
            owner = options.Value.Owner;
            repoName = options.Value.RepoName;
            branchName = options.Value.BranchName;
            token = options.Value.Token;
        }

        private GitHubClient GetGitClient()
        {

            var client = new GitHubClient(new ProductHeaderValue(repoName));
            var tokenAuth = new Credentials(token); // 使用你的GitHub个人访问令牌
            client.Credentials = tokenAuth;

            return client;
        }
        public async Task<byte[]> Download(string fileId)
        {
            var client = GetGitClient();
            try
            {
                var resource = await GetResourceInfo(fileId);
                return await Download(resource);
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        public async Task<byte[]> Download(ResourceInfo resource)
        {
            var client = GetGitClient();
            try
            {
                if (resource == null)
                {
                    return null;
                }

                // 获取最新的提交SHA（如果你需要下载特定分支的文件）
                var repo = await client.Repository.Get(owner, repoName);
                var branch = await client.Repository.Branch.Get(owner, repoName, branchName);  // 假设使用main分支
                //根据实际的文件信息下载文件
                var filePath = $"{resource.FullPath.Trim('/')}{fileSubfix}";
                // 获取文件的 blob SHA
                var content = await client.Repository.Content.GetAllContents(owner, repoName, HttpUtility.UrlEncode(filePath));
                var blobSha = content[0].Sha;  // 假设文件只有一个 blob
                // 获取文件的blob信息
                var fileContent = await client.Git.Blob.Get(owner, repoName, blobSha);
                // GitHub返回的文件是Base64编码的
                var decodedContent = Convert.FromBase64String(fileContent.Content);
                var realContent = Encoding.UTF8.GetString(decodedContent);
                return Convert.FromBase64String(realContent);
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        public async Task<ResourceInfo> Upload(byte[] data, string fileName, string path)
        {

            var fileId = Encrypt.MD5Encrypt32($"{path}/{fileName}");
            var resource = await GetResourceInfo(fileId);
            if (resource != null)
            {
                return resource;
            }


            //按源文件路径保存
            var realPath = await UploadFile(data, fileName, path);
            if (string.IsNullOrWhiteSpace(realPath))
            {
                return null;
            }

            //生产文件id并映射源文件路径
            resource = new ResourceInfo
            {
                FullPath = realPath,
                Name = fileName,
                Length = data.Length,
                Subfix = Path.GetExtension(fileName),
                Id = Guid.NewGuid().ToString(),
            };

            var resourceContent = JsonConvert.SerializeObject(resource);
            await UploadFile(Encoding.UTF8.GetBytes(resourceContent), resource.Id.ToString(), "ResourceInfo");


            try
            {
                var localResourceInfoPath = Path.Combine(AppContext.BaseDirectory, "ResourceInfo");
                if (!Directory.Exists(localResourceInfoPath))
                {
                    Directory.CreateDirectory(localResourceInfoPath);
                }
                System.IO.File.WriteAllText(Path.Combine(localResourceInfoPath, resource.Id), resourceContent);
            }
            catch (Exception)
            {

            }


            return resource;
        }

        public async Task<ResourceInfo> GetResourceInfo(string fileId)
        {
            var client = GetGitClient();
            try
            {
                try
                {
                    var filePath = Path.Combine(AppContext.BaseDirectory, "ResourceInfo", fileId);
                    if (System.IO.File.Exists(filePath))
                    {
                        return JsonConvert.DeserializeObject<ResourceInfo>(System.IO.File.ReadAllText(filePath));
                    }
                }
                catch (Exception)
                {

                }

                // 获取最新的提交SHA（如果你需要下载特定分支的文件）
                var repo = await client.Repository.Get(owner, repoName);
                var branch = await client.Repository.Branch.Get(owner, repoName, branchName);  // 假设使用main分支

                //根据id 获取文件信息
                var idPath = $"ResourceInfo/{fileId}{fileSubfix}";
                var fileIdContent = await client.Repository.Content.GetAllContents(owner, repoName, HttpUtility.UrlEncode(idPath));
                var content = Encoding.UTF8.GetString(Convert.FromBase64String(fileIdContent[0].Content));
                var resource = JsonConvert.DeserializeObject<ResourceInfo>(content);

                return resource;
            }
            catch (Exception ex)
            {
                return null;
            }
        }


        private async Task<string> UploadFile(byte[] data, string fileName, string path)
        {

            var client = GetGitClient();
            var commitMessage = "file upload test";
            var resultPath = $"{(string.IsNullOrWhiteSpace(path) ? "" : $"{path}/")}{HttpUtility.UrlEncode(fileName)}";
            var filePath = $"{resultPath}{fileSubfix}";
            var fileContent = Convert.ToBase64String(data);
            try
            {
                var repo = await client.Repository.Get(owner, repoName);
                var branch = await client.Repository.Branch.Get(owner, repoName, branchName);
                var latestCommit = branch.Commit;
                var tree = await client.Git.Tree.Get(owner, repoName, latestCommit.Sha);

                var newTreeItem = new NewTreeItem
                {
                    Path = filePath,
                    Mode = "100644",
                    Type = TreeType.Blob,
                    Content = fileContent
                };

                var newTree = new NewTree { BaseTree = tree.Sha };
                newTree.Tree.Add(newTreeItem);
                var createdTree = await client.Git.Tree.Create(owner, repoName, newTree);

                var newCommit = new NewCommit(commitMessage, createdTree.Sha, latestCommit.Sha);
                var commit = await client.Git.Commit.Create(owner, repoName, newCommit);

                var updateReference = new ReferenceUpdate(commit.Sha);
                await client.Git.Reference.Update(owner, repoName, $"heads/{branchName}", updateReference);

                return resultPath;
            }
            catch (Exception ex)
            {
                Console.Error.WriteLine(ex.StackTrace);
                return string.Empty;
            }
        }
    }
}
